package com.api.shop.service.impl;

import com.api.shop.bean.SysPermission;
import com.api.shop.bean.SysRole;
import com.api.shop.bean.SysUser;
import com.api.shop.bean.QkLoginInfo;
import com.api.shop.common.RequestHolder;
import com.api.shop.common.ReturnData;
import com.api.shop.dao.*;
import com.api.shop.exception.MyDataException;
import com.api.shop.exception.ParamException;
import com.api.shop.service.UserService;
import com.api.shop.util.*;
import com.api.shop.util.fileUpload.FileUtils;
import com.api.shop.util.redis.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Auther: wyx
 * @Date: 2019-04-03 11:13
 * @Description: 用户相关操作
 */

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    //TODO 定时销毁
    private static Map<String, QkLoginInfo> loginInfoMap = new HashMap<>();
    @Resource
    private SysUserDao sysUserDao;
    @Resource
    private UserRoleDao userRoleDao;
    @Resource
    private SysRoleDao sysRoleDao;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private SysPermissionDao sysPermissionDao;
    @Resource
    private RolePermissionDao rolePermissionDao;
    // 图片上传路径
    @Value("${web.upload-path}")
    private String path;

    @Transactional
    @Override
    public ReturnData register( SysUser sysUser, HttpServletRequest request) {


        BeanValidator.check(sysUser);

        SysUser user = sysUserDao.selectUserByName(sysUser.getUsername());
        if(user != null){
            throw new ParamException("该用户名已存在: " + sysUser.getUsername());
        }

        sysUser.setPassword(MD5Util.getEncoderStr(sysUser.getPassword()));
        sysUser.setAvatar("http://yjjvip.cn:8080/pictures/default.jpg");
        log.info("编码后的密码: {}", sysUser.getPassword());
        int lineUser = sysUserDao.insert(sysUser);
        int lineRole = userRoleDao.insertIntoRole(sysUser.getUserId(), 4);
        if(lineUser == 1 && lineRole == 1){
            log.info("用户:{} 注册成功", sysUser.getUsername());
            return ReturnData.success();
        }else{
            throw new MyDataException("用户数据插入数据库失败");
        }
    }

    @Override
    public ReturnData upAvatar(MultipartFile avatarPicture, HttpServletRequest request) {
        SysUser sysUser = RequestHolder.getCurrentUser();
        if(sysUser == null){
            throw new MyDataException("用户信息不存在");
        }
        String avatarUrl = FileUtils.upload(avatarPicture);
        sysUser.setAvatar(avatarUrl);
        sysUserDao.upAvatar(sysUser);
        return ReturnData.success();
    }

    @Override
    public ReturnData login(String username, String psw, HttpServletRequest request) {
        SysUser user = sysUserDao.selectUserByName(username);
        if(user == null){
            throw new ParamException("该用户名不存在: " + username);
        }
        log.info("user: " + user.toString());

        String encodePsw = MD5Util.getEncoderStr(psw);

        if(!encodePsw.equals(user.getPassword())){
            throw new ParamException("用户名或密码错误");
        }

        String ip = IpUtil.getIpAddr(request);

        log.info("用户:{}, ip: {} 登录成功", ip , user.getUsername());
//        String token = JWTUtil.createToken(username);
        String token = MyTokenUtil.createToken(ip, username);

        redisUtil.set(token.trim(), user.toString());
        redisUtil.set("userId_" + user.getUserId(), token.trim());
        redisUtil.expire(token.trim(), 60 * 60 * 6);
        redisUtil.expire(user.getUserId() + "", 60 * 60 * 6);
        RequestHolder.add(user);

        ArrayList<Integer> roleIdList = userRoleDao.selectRoleIdListByUserId(user.getUserId());
        if(roleIdList.isEmpty()){
            return ReturnData.fail("该用户无角色");
        }
        ArrayList<String> roleNameList = sysRoleDao.selectRoleNameByIdList(roleIdList);

        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("nikeName",user.getNickName());
        map.put("roleNameList", roleNameList);
        return ReturnData.success(map);
    }



    @Override
    public ReturnData sendSMS(String phoneNumber) {

        loginInfoMap.remove(phoneNumber);
        if(phoneNumber ==null || phoneNumber.length() == 0){

            throw new ParamException("手机号码不能为空");
        }

        String code = QkLoginUtil.KeyParam();
        if( code.length() == 0){

            throw new ParamException("验证码不能为空");
        }
        try{

            QkLoginUtil.sendSMS(phoneNumber,code);
        }
        catch (ParamException e){

            throw new ParamException(e.getMessage());
        }

        //接口bug？
        code = code.substring(1,code.length()-1);
        QkLoginInfo qkLoginInfo = new QkLoginInfo();
        qkLoginInfo.setCode(code);
        qkLoginInfo.setCodeDate(new Date());
        loginInfoMap.put(phoneNumber,qkLoginInfo);
        return ReturnData.success();
    }

    @Override
    public ReturnData qkLogin(String phoneNumber, String code, HttpServletRequest request) {

        //格式校验
        if(loginInfoMap.size() == 0){

            throw new ParamException("请先获取验证码");
        }
        if(phoneNumber == null ||phoneNumber.length() == 0){

            throw new ParamException("手机号码不能为空");
        }

        if(code == null || code.length() == 0){

            throw new ParamException("验证码不能为空");
        }

        QkLoginInfo qkLoginInfo = loginInfoMap.get(phoneNumber);
        if(qkLoginInfo.getCode() == null){

            throw new ParamException("未成功获取验证码");
        }
        if(!loginInfoMap.containsKey(phoneNumber)){

            throw new ParamException("未成功获取验证码");
        }
        if(!code.equals(qkLoginInfo.getCode())){

            log.info("用户输入验证码{},系统验证码{}",code,qkLoginInfo.getCode());
            throw  new ParamException("验证码不正确");
        }
        loginInfoMap.remove(phoneNumber);
        if(System.currentTimeMillis() - qkLoginInfo.getCodeDate().getTime() > QkLoginInfo.codeOutTime){

            throw new ParamException("验证码过期");
        }

        //如果用户第一次登录，在数据库中注册该用户
        SysUser sysUser = sysUserDao.selectUserByName(phoneNumber);
        if(sysUser == null){

            sysUser = QkLoginUtil.setPhoneUser(phoneNumber);
            int line1 = sysUserDao.insert(sysUser);
            int line2 = userRoleDao.insertIntoRole(sysUser.getUserId(),4);
            if(line1 != 1 || line2 != 1){

                throw new ParamException("用户登录或注册失败");
            }

        }
        String ip = IpUtil.getIpAddr(request);
        log.info("用户:{}, ip: {} 登录成功", ip , sysUser.getUsername());
        String token = MyTokenUtil.createToken(ip, sysUser.getUsername());

        redisUtil.set(token.trim(), sysUser.toString());
        redisUtil.set("userId_" + sysUser.getUserId(), token.trim());
        redisUtil.expire(token.trim(), 60 * 60 * 6);
        redisUtil.expire(sysUser.getUserId() + "", 60 * 60 * 6);

        RequestHolder.add(sysUser);
        ArrayList<Integer> roleIdList = userRoleDao.selectRoleIdListByUserId(sysUser.getUserId());
        if(roleIdList.isEmpty()){
            return ReturnData.fail("该用户无角色");
        }
        ArrayList<String> roleNameList = sysRoleDao.selectRoleNameByIdList(roleIdList);

        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("roleNameList", roleNameList);
        return ReturnData.success(map);

    }

    @Override
    public ReturnData logout(HttpServletRequest request) {
        SysUser user = RequestHolder.getCurrentUser();
        if(user == null){
            throw new RuntimeException("用户信息不存在");
        }

        log.info("user: {}, token: {}", RequestHolder.getCurrentUser(), RequestHolder.getCurrentToken());
        redisUtil.delete(RequestHolder.getCurrentToken().trim(), "userId_" + RequestHolder.getCurrentUser().getUserId());
        RequestHolder.remove();
        log.info("用户:{} 注销成功", user.getUsername());
        return ReturnData.success();
    }

    @Override
    public ReturnData showMessage(HttpServletRequest request) {
        SysUser user = RequestHolder.getCurrentUser();
        if(user == null){
            throw new RuntimeException("用户信息不存在");
        }
        return ReturnData.success(user);
    }

    @Override
    public ReturnData exchangeMessage(String nickName, HttpServletRequest request) {
        SysUser user = RequestHolder.getCurrentUser();
        if(user == null){
            throw new RuntimeException("用户信息不存在");
        }

        user.setNickName(nickName);

        int line = sysUserDao.update(user);
        if(line == 1){
            RequestHolder.removeUser();
            RequestHolder.add(user);
            log.info("用户{} 信息修改成功", user.getUsername());
            return ReturnData.success();
        }
        return ReturnData.fail("用户信息修改失败");
    }

    @Override
    public ReturnData validateAuth(String needAuthUrl, HttpServletRequest request) {
        SysUser user = RequestHolder.getCurrentUser();
        if(user == null){
            throw new RuntimeException("用户信息不存在");
        }

        ArrayList<Integer> permissionIdList = sysPermissionDao.selectIdsByUrl(needAuthUrl + "%");
        if(permissionIdList == null || permissionIdList.isEmpty()){
            log.info("该 URL:{} 未绑定相关权限", needAuthUrl);
            return ReturnData.success("该 URL 未绑定相关权限");
        }

        ArrayList<Integer> roleIdList = rolePermissionDao.selectRoleIdByPermissionIdList(permissionIdList);
        if(roleIdList == null || roleIdList.isEmpty()){
            throw new MyDataException("该权限未绑定角色，无法使用");
        }

        ArrayList<Integer> userRoleId = userRoleDao.selectRoleIdListByUserId(user.getUserId());

        for(Integer permissionRoleId: roleIdList){
            if(userRoleId.contains(permissionRoleId)){
                log.info("该用户有访问该 URL: {} 的权限 id: {}", needAuthUrl, permissionRoleId);
                return ReturnData.success();
            }
        }

        log.info("该用户没有权限访问该 URL:{}", needAuthUrl);
        return ReturnData.fail("该用户没有权限访问该 URL");
    }

    /**
     * 返回该用户的全部角色
     */
    private ReturnData showAllRoles(HttpServletRequest request) {
        SysUser user = RequestHolder.getCurrentUser();
        if(user == null){
            throw new MyDataException("用户信息不存在");
        }

        ArrayList<Integer> roleIdList = userRoleDao.selectRoleIdListByUserId(user.getUserId());if(roleIdList.isEmpty()){
            throw new MyDataException("该用户无角色");
        }
        ArrayList<SysRole> roleList = sysRoleDao.selectRolesByIdList(roleIdList);

        return ReturnData.success(roleList);
    }

    /**
     * 返回该 url 需要的权限
     */
    private ReturnData showAllPermissionsByUrl(String permissionUrl, HttpServletRequest request) {
        ArrayList<SysPermission> permissionList = sysPermissionDao.selectByUrl(permissionUrl);
        if(permissionList == null || permissionList.isEmpty()){
            throw new MyDataException("安全警告： 该 URL 未设置访问权限");
        }

        return ReturnData.success(permissionList);
    }
}
